#include <croco/os/thread_sync.hpp>

croco::os::thread_sync::thread_sync()
: m_started(false)
{
}

void croco::os::thread_sync::set_thread(boost::thread& t)
{
    m_thread.swap(t);
}

void croco::os::thread_sync::wait_for_start() const
{
    boost::unique_lock<boost::mutex> lock(m_startSentinel);
    while(!m_started)
    {
        m_startCV.wait(lock);
    }
    if(m_exc)
    {
        boost::rethrow_exception(m_exc);
    }
}

void croco::os::thread_sync::signal_started(const boost::exception_ptr& e)
{
    boost::unique_lock<boost::mutex> lock(m_startSentinel);
    m_exc = e;
    m_started = true;
    m_startCV.notify_all();
}

void croco::os::thread_sync::set_error(const boost::exception_ptr& e)
{
    assert(e);
    {
        boost::unique_lock<boost::mutex> lock(m_startSentinel);
        if(m_started)
        {
            m_exc = e;
            return;
        }
    }
    signal_started(e);
}

void croco::os::thread_sync::join()
{
    m_thread.join();
    if(m_exc)
    {
        boost::rethrow_exception(m_exc);
    }
}
